/********************************************************************************
 * @file    app_iot_ctrl.c
 * @brief   物联网控制应用逻辑处理
 * 
 * @author  nzttj
 * @date    2025-02-18
 * @version 1.0
 * 
 * Copyright (C) 2025 nzttj
 * 
 * 本软件使用 GNU 通用公共许可证 (GPL) 第 3 版授权。
 * 
 * 您可以自由使用、修改、分发本软件，但必须遵守以下条件：
 * 1. 源代码必须开放，且您修改后的代码也必须以 GPL 许可证发布。
 * 2. 发布或分发本软件时，必须附带本许可证，并提供源代码或获取源代码的方式。
 * 
 * 本软件按“原样”提供，不附带任何担保，使用风险由用户自行承担。
 * 
 ********************************************************************************/

#include "app_iot_ctrl.h"
#include "app_nvs.h"
#include "button.h"
#include "cn8023a.h"
#include "app_udp.h"
#include "app_energy_storage.h"

#include "esp_log.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include <string.h>

// 配网长按时间
#define APP_PROVISION_MS (3000)
// 恢复出厂设置长按时间
#define APP_RESTORE_FACTORY_MS (10000)

static const char *TAG = "app_iot_ctrl";
static app_iot_device_state_t s_device_state = {
    .led_on = 0,
    .socket_on = 0,
    .led_enabled = 1,
    .child_lock = 0,
    .power_on_state = POWER_ON_STATE_LAST,
};
static QueueHandle_t s_iot_ctrl_queue = NULL;
static TaskHandle_t s_led_flash_task = NULL;

static void _app_iot_ctrl_task(void *arg)
{
    for (;;)
    {
        iot_ctrl_t iot_ctrl;
        if (xQueueReceive(s_iot_ctrl_queue, &iot_ctrl, portMAX_DELAY) == pdPASS)
        {
            switch (iot_ctrl.type)
            {
            case IOT_CTRL_TYPE_CN8023A:
                if (iot_ctrl.value)
                {
                    ESP_LOGI(TAG, "CN8023A Open");
                    cn8023a_open();
                }
                else
                {
                    ESP_LOGI(TAG, "CN8023A Close");
                    cn8023a_close();
                }
                s_device_state.led_on = iot_ctrl.value;
                app_iot_ctrl_led(s_device_state.led_on);
                app_udp_package_send(CMD_SET_SWITCH_STATE, (const uint8_t *)&iot_ctrl.value, 1);
                char *report_data = iot_ctrl.value ? "on" : "off";
                app_mqtt_data_report(report_data, strlen(report_data));
                app_nvs_save_device_state(&s_device_state);
                break;
            default:
                break;
            }
        }
    }
}

static void _button_event_handler(button_event_t event, uint32_t press_duration_ms, void *arg)
{
    // 如果儿童安全锁开启，则忽略按键事件
    if (s_device_state.child_lock) {
        ESP_LOGI(TAG, "Child lock is enabled, ignoring button event");
        return;
    }

    switch (event)
    {
    case BUTTON_EVENT_PRESSED:
        ESP_LOGI(TAG, "Button Pressed");
        break;
    case BUTTON_EVENT_RELEASED:
        ESP_LOGI(TAG, "Button Released, duration: %d ms", press_duration_ms);
        if (press_duration_ms >= APP_PROVISION_MS && press_duration_ms < APP_RESTORE_FACTORY_MS)
        {
            // 进入配网模式
            ESP_LOGI(TAG, "Provisioning");
            app_nvs_save_wifi_mode(HAL_WIFI_MODE_AP);
            vTaskDelay(1000);
            esp_restart();
        }
        else if (press_duration_ms >= APP_RESTORE_FACTORY_MS)
        {
            ESP_LOGI(TAG, "Restore Factory");
            // 恢复出厂设置
            app_nvs_restore_factory();
            app_energy_storage_delete_all_records();
            vTaskDelay(1000);
            esp_restart();
        }
        break;
    case BUTTON_EVENT_SINGLE_CLICK:
        ESP_LOGI(TAG, "Single Click");
        iot_ctrl_t iot_ctrl = {.type = IOT_CTRL_TYPE_CN8023A, .value = !s_device_state.led_on};
        xQueueOverwrite(s_iot_ctrl_queue, &iot_ctrl);
        break;
    case BUTTON_EVENT_LONG_PRESSED:
        ESP_LOGI(TAG, "Long Pressed, duration: %d ms", press_duration_ms);
        break;
    }
}

static void _app_iot_ctrl_button_init(void)
{
    button_config_t config = {
        .gpio_num = APP_BUTTON_CTRL_IO,
        .debounce_time_ms = 50,
        .long_press_time_ms = APP_PROVISION_MS,
        .active_low = true,
        .pull_up_en = true,
        .pull_down_en = false,
        // .repeat_long_press = true,      // 启用重复触发
        // .repeat_interval_ms = 100,      // 每100ms触发一次
    };

    button_system_init();
    button_handle_t btn = button_init(&config);
    button_register_cb(btn, _button_event_handler, NULL);
}

static void _app_iot_ctrl_led_init(void)
{
#if APP_LED_CTRL_ENABLE
    gpio_config_t io_conf = {};
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = 1ULL << APP_LED_CTRL_IO;
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 0;
    gpio_config(&io_conf);

    app_iot_ctrl_led(s_device_state.led_on);
#endif // APP_LED_CTRL_ENABLE
}

int app_iot_ctrl_led(int level)
{
#if APP_LED_CTRL_ENABLE
    // 如果LED禁用，则关闭LED
    if (!s_device_state.led_enabled) {
        gpio_set_level(APP_LED_CTRL_IO, 1);  // 关闭LED
        return 0;
    }

    // 根据亮度设置LED
    if (level) {
        gpio_set_level(APP_LED_CTRL_IO, 0);  // 开启LED
    } else {
        gpio_set_level(APP_LED_CTRL_IO, 1);  // 关闭LED
    }
#endif // APP_LED_CTRL_ENABLE
    return 0;
}

static void _app_iot_ctrl_socket_init(void)
{
#if APP_SOCKET_CTRL_ENABLE
    gpio_config_t io_conf = {};
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = 1ULL << APP_SOCKET_CTRL_IO;
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 0;
    gpio_config(&io_conf);

    app_iot_ctrl_socket(s_device_state.socket_on);
#endif // APP_SOCKET_CTRL_ENABLE
}

int app_iot_ctrl_socket(int level)
{
#if APP_SOCKET_CTRL_ENABLE
    gpio_set_level(APP_SOCKET_CTRL_IO, !level);
#endif // APP_SOCKET_CTRL_ENABLE
    return 0;
}

int app_iot_ctrl_init(void)
{
    // 创建队列
    s_iot_ctrl_queue = xQueueCreate(1, sizeof(iot_ctrl_t));
    if (s_iot_ctrl_queue == NULL)
    {
        ESP_LOGE(TAG, "Failed to create queue");
        return -1;
    }

    // 创建任务
    if (xTaskCreate(_app_iot_ctrl_task, "app_iot_ctrl", 2048, NULL, 20, NULL) != pdPASS)
    {
        vQueueDelete(s_iot_ctrl_queue);
        s_iot_ctrl_queue = NULL;
        ESP_LOGE(TAG, "Failed to create task");
        return -1;
    }

    iot_ctrl_t iot_ctrl = {.type = IOT_CTRL_TYPE_CN8023A};

    // 根据断电后上电状态配置设置初始状态
    switch (s_device_state.power_on_state)
    {
    case POWER_ON_STATE_ON:
        s_device_state.led_on = 1;
        s_device_state.socket_on = 1;
        iot_ctrl.value = 1;
        xQueueSend(s_iot_ctrl_queue, &iot_ctrl, portMAX_DELAY);
        break;
    case POWER_ON_STATE_OFF:
        s_device_state.led_on = 0;
        s_device_state.socket_on = 0;
        iot_ctrl.value = 0;
        xQueueSend(s_iot_ctrl_queue, &iot_ctrl, portMAX_DELAY);
        break;
    case POWER_ON_STATE_LAST:
    default:
        // 保持断电前状态，不需要修改
        break;
    }

    _app_iot_ctrl_led_init();
    _app_iot_ctrl_socket_init();
    _app_iot_ctrl_button_init();
    return 0;
}

int app_iot_ctrl_data_parse(const char *data, int len)
{
    iot_ctrl_t iot_ctrl = {.type = IOT_CTRL_TYPE_CN8023A, .value = 0};

    if (strncmp(data, "on", len) == 0)
    {
        iot_ctrl.value = 1;
    }
    else if (strncmp(data, "off", len) == 0)
    {
        iot_ctrl.value = 0;
    }
    else
    {
        ESP_LOGE(TAG, "Invalid data: %s", data);
        return -1;
    }

    xQueueOverwrite(s_iot_ctrl_queue, &iot_ctrl);

    return 0;
}

int app_iot_ctrl_with_queue(iot_ctrl_t *iot_ctrl)
{
    if (s_iot_ctrl_queue)
    {
        xQueueSend(s_iot_ctrl_queue, iot_ctrl, portMAX_DELAY);
    }
    return 0;
}

static void _led_flash_task(void *param)
{
    uint32_t count = 0;
    uint32_t flash_ms = (uint32_t)param;

    for (;;)
    {
        app_iot_ctrl_led(count++ % 2);
        vTaskDelay(flash_ms);
    }
}

int app_iot_ctrl_led_flash_start(uint32_t flash_ms)
{
    if (s_led_flash_task)
    {
        ESP_LOGW(TAG, "LED flash task already running");
        return 0;
    }

    return xTaskCreate(_led_flash_task, "led_flash", 256, (void *)pdMS_TO_TICKS(flash_ms), 13, &s_led_flash_task) == pdPASS ? 0 : -1;
}

int app_iot_ctrl_led_flash_stop(void)
{
    if (s_led_flash_task)
    {
        vTaskDelete(s_led_flash_task);
        s_led_flash_task = NULL;
    }
    return 0;
}

app_iot_device_state_t *app_iot_ctrl_get_device_state(void)
{
    return &s_device_state;
}

int app_iot_ctrl_set_child_lock(uint8_t lock)
{
    s_device_state.child_lock = lock;
    app_nvs_save_device_state(&s_device_state);
    ESP_LOGI(TAG, "Child lock %s", lock ? "enabled" : "disabled");
    return 0;
}

int app_iot_ctrl_set_led_state(uint8_t enabled)
{
    s_device_state.led_enabled = enabled;
    app_nvs_save_device_state(&s_device_state);
    
    // 如果LED禁用，关闭LED
    if (!enabled) {
        app_iot_ctrl_led(0);
    } else {
        // 根据当前开关状态设置LED
        app_iot_ctrl_led(s_device_state.led_on);
    }

    ESP_LOGI(TAG, "LED %s", enabled ? "enabled" : "disabled");
    return 0;
}

int app_iot_ctrl_set_power_on_state(power_on_state_t state)
{
    if (state > POWER_ON_STATE_OFF) {
        ESP_LOGE(TAG, "Invalid power on state: %d", state);
        return -1;
    }

    s_device_state.power_on_state = state;
    app_nvs_save_device_state(&s_device_state);
    ESP_LOGI(TAG, "Power on state set to: %d", state);
    return 0;
}

power_on_state_t app_iot_ctrl_get_power_on_state(void)
{
    return s_device_state.power_on_state;
}
